/******************* Contiene las variables y funciones globales ****************/

#ifndef GLOBAL_H
#define GLOBAL_H

//Incluyo la clase mt.cpp para valores aleatorios
#include "mt.h"

/******************* Declaracion de Variables globales del Host ****************/
int cantidadParametros = 23;

int tipoRepresentacion;
int totalGenesGPU;
int totalGenesCPU;
int totalIndividuosGPU;
int totalIndividuosCPU;
int cantidadPoblacionesGPU;
int cantidadPoblacionesCPU;
int cantCromosomasPoblacion;
int cantGenesEnCromosoma;
int numeroGeneraciones;
int bloquePorPoblacion;
int totalGenesEnPoblacion;
int tipoCruzamiento;
int tipoMutacion;
float probabilidadCruzamiento;
float probabilidadMutacion;
int tipoReemplazo;
int tipoSeleccion;
float gradoNoUniformidad;
float porcentajeElitismo;
int generacionesMigrar;
int modoDebug;
int imprimirPoblacionEntera;
int cantidadIndividuosSeleccionPorRango;
int inicializacionAutomatica;
float inicioRango;
float finRango;
int cantHilosBloque;

/******************* Declaracion de Variables globales del Device ****************/
__device__ int cantidadPoblacionesGPUDevice;
__device__ int cantidadPoblacionesCPUDevice;
__device__ int cantCromosomasPoblacionDevice;
__device__ int cantGenesEnCromosomaDevice;
__device__ int totalGenesEnPoblacionDevice;
__device__ int tipoCruzamientoDevice;
__device__ int tipoMutacionDevice;
__device__ float probabilidadCruzamientoDevice;
__device__ float probabilidadMutacionDevice;
__device__ int tipoReemplazoDevice;
__device__ int tipoSeleccionDevice;
__device__ int numeroGeneracionesDevice;
__device__ float gradoNoUniformidadDevice;
__device__ float porcentajeElitismoDevice;
__device__ int cantidadIndividuosSeleccionPorRangoDevice;
__device__ int generacionesMigrarDevice;
__device__ int imprimirPoblacionEnteraDevice;
__device__ int metodoInicializacionDevice;
__device__ float inicioRangoDevice;
__device__ float finRangoDevice;
__device__ int cantHilosBloqueDevice;

/******************* Declaracion de Funciones Global del Device ******************/
__global__ void asignarParametrosDevice(int * parametros);

/******************* Declaracion de Funciones internas del Device *****************/
__device__ int estaPresente(int valor, int* nuevaPoblacion, int desde, int hasta);
__device__ int posicionPrimerLibre(int* poblacionActual, int posicionNuevoCromosoma);
__device__ int dondeEsta(int* poblacionActual, int valor, int posicionNuevoCromosoma);
__global__ void ordenarDescendente(float *fitnesAOrdenar, int *indicesFitnessOrdenado);
__device__ int obtenerNumeroEnRangoEntera(unsigned long valor);
__device__ int obtenerNumeroEnRangoPermutacion(unsigned long valor);
__device__ float obtenerNumeroEnRangoReal(float valor);

/******************* Declaracion de Funciones del Host *************************/
void asignarParametros(int * parametros);
int estaPresenteCPU(int valor, int* nuevaPoblacion, int desde, int hasta);
int posicionPrimerLibreCPU(int* poblacionActual, int posicionNuevoCromosoma);
int dondeEstaCPU(int* poblacionActual, int valor, int posicionNuevoCromosoma);
void ordenarDescendenteCPU(float *fitnesAOrdenar, int *indicesFitnessOrdenado, int nroPoblacion);
void generarNumerosAleatoriosBinaria(MersenneTwister *mt, unsigned long* numerosAleatoriosInicializacion, unsigned long* numerosAleatoriosSeleccion, unsigned long* numerosAleatoriosCruzamiento, unsigned long* numerosAleatoriosMutacion, unsigned long* numerosAleatoriosProbabilidadCruzamiento, unsigned long* numerosAleatoriosProbabilidadMutacion);
void generarNumerosAleatoriosEntera(MersenneTwister *mt, unsigned long* numerosAleatoriosInicializacion, unsigned long* numerosAleatoriosSeleccion, unsigned long* numerosAleatoriosCruzamiento, unsigned long* numerosAleatoriosMutacion, unsigned long* numerosAleatoriosProbabilidadCruzamiento, unsigned long* numerosAleatoriosProbabilidadMutacion);
void generarNumerosAleatoriosPermutacion(MersenneTwister *mt, unsigned long* numerosAleatoriosInicializacion, unsigned long* numerosAleatoriosSeleccion, unsigned long* numerosAleatoriosCruzamiento, unsigned long* numerosAleatoriosMutacion, unsigned long* numerosAleatoriosProbabilidadCruzamiento, unsigned long* numerosAleatoriosProbabilidadMutacion);
void generarNumerosAleatoriosReal(MersenneTwister *mt, float* numerosAleatoriosInicializacion, unsigned long* numerosAleatoriosSeleccion, unsigned long* numerosAleatoriosCruzamiento, unsigned long* numerosAleatoriosMutacion, unsigned long* numerosAleatoriosProbabilidadCruzamiento, unsigned long* numerosAleatoriosProbabilidadMutacion);
int obtenerNumeroEnRangoEnteraCPU(unsigned long valor);
int obtenerNumeroEnRangoPermutacionCPU(unsigned long valor);
float obtenerNumeroEnRangoRealCPU(float valor);

#endif  // GLOBAL_H
